package it.unipg.bipod.web;

import it.unipg.bipod.applicationLogic.*;
import it.unipg.bipod.dataModel.*;

import java.io.*;
import java.text.*;

import java.sql.Timestamp;
import java.util.Vector;

import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

/**
 * GestioneBandoBean incapsula un bando e permette di effettuare su di esso alcune operazioni
 * associate ad un utente di segreteria.<br>
 * Questa classe contiene la sottoclasse pubblica InsegnamentoBean.<br>
 * Eventuali messaggi o errori vengono segnalati mediante i metodi forniti da DefaultBean.
 * 
 * @author Lorenzo Porzi
 * @see DefaultBean
 * @see SegretarioBandiBean
 */
public class GestioneBandoBean extends DefaultBean {
	private SegretarioApplication application;
	private SegretarioBandiBean bandiBean;
	
	private Bando bando; // Il bando incapsulato
	private InsegnamentoBean[] insegnamenti; // Gli insegnamenti appartenenti al bando

	/**
	 * Crea un nuovo GestionBandoBean con i parametri specificati.<br>
	 * Gli insegnamenti appartenenti al bando vengono letti immediatamente.
	 * 
	 * @param application la {@link SegretarioApplication} collegata a questo oggetto.
	 * @param bandiBean il {@link SegretarioBandiBean} da cui dipende questo oggetto.
	 * @param bando il bando incapsulato da questo oggetto.
	 */
	public GestioneBandoBean(SegretarioApplication application, SegretarioBandiBean bandiBean, Bando bando) {
		super();
		
		this.application = application;
		this.bando = bando;
		this.bandiBean = bandiBean;
		
		try {
			// Legge gli insegnamenti
			InsegnamentoCorso[] insegnamenti = application.getInsegnamenti(bando);
			
			// Li incapsula nei beans
			InsegnamentoBean[] insegnamentiBean = new InsegnamentoBean[insegnamenti.length];
			for (int i = 0; i < insegnamenti.length; ++i)
				insegnamentiBean[i] = new InsegnamentoBean(insegnamenti[i]);
			
			this.insegnamenti = insegnamentiBean;
		} catch (ApplicationException e) {
			// Ritorna un array vuoto
			InsegnamentoBean[] vuoto = {};
			this.insegnamenti = vuoto;
		}
	}
	
	/* --------------------------------------------------------
	 * Getters e setters per le proprietà del bando incapsulato
	 * -------------------------------------------------------- */
	
	public int getIdBando() {
		return bando.getIdBando();
	}
	
	public String getDataPubblicazione() {
		Format dateFormat = new SimpleDateFormat("dd/MM/yyyy");
		return dateFormat.format(bando.getDataPubblicazione());
	}
	
	public String getDataInserimento() {
		Format dateFormat = new SimpleDateFormat("dd/MM/yyyy");
		return dateFormat.format(bando.getDataInserimento());
	}
	
	public String getDataScadenza() {
		Format dateFormat = new SimpleDateFormat("dd/MM/yyyy");
		return dateFormat.format(bando.getDataScadenza());
	}
	
	/**
	 * @return lo stato di attività del bando incapsulato.
	 */
	public boolean getAttivo() {
		Timestamp now = new Timestamp(System.currentTimeMillis());
		
		return bando.getDataScadenza().after(now) && bando.getDataPubblicazione().before(now);
	}
	
	/* --------------------------------
	 * Metodi per l'estrazione dei dati
	 * -------------------------------- */
	
	/**
	 * Restituisce l'elenco degli insegnamenti appartenenti a questo bando.
	 * 
	 * @return un array di InsegnamentoBean in cui ogni elemento incapsula un insegnamento
	 * di questo bando.
	 */
	public InsegnamentoBean[] getInsegnamenti() {
		return insegnamenti;
	}
	
	/**
	 * Restituisce il numero di insegnamenti appartenenti a questo bando.
	 * 
	 * @return il numero di insegnamenti di questo bando.
	 */
	public int getNumeroInsegnamenti() {
		return insegnamenti.length;
	}
	
	/* ---------------------
	 * Metodi di navigazione
	 * --------------------- */
	
	/**
	 * Imposta questo come bando corrente e restituisce il nome della pagina di dettaglio bando.
	 * 
	 * @return "/pages/segretario-bando-dettaglio"
	 */
	public String vedi() {
		bandiBean.setBandoCorrente(this);
		
		return "/pages/segretario-bando-dettaglio";
	}
	
	/**
	 * Genera un verbale per questo bando.
	 * Questo metodo utilizza le seguenti proprieta' di presentation.ini:
	 * <ul>
	 *   <li><b>msgErroreVerbaleVuoto</b>: il messaggio visualizzato quando il verbale sarebbe vuoto.</li>
	 *   <li><b>msgErroreGenerazioneVerbale</b>: il messaggio visualizzato quando si verifica un errore.</li>
	 * </ul>
	 */
	public void scriviVerbale() {		
		InsegnamentoDocente[] ids = new InsegnamentoDocente[insegnamenti.length];
		for (int i = 0; i < ids.length; ++i) {
			if (insegnamenti[i].getNumeroRichieste() == 0 ||
					insegnamenti[i].getAssegnazione() instanceof RichiestaNonAssegnata)
				ids[i] = new InsegnamentoDocente(null, insegnamenti[i].getInsegnamento().getInsegnamento());
			else
				ids[i] = new InsegnamentoDocente(insegnamenti[i].getAssegnazione().getDocente(), insegnamenti[i].getInsegnamento().getInsegnamento());
		}
		
		// Genera il documento
		try {
			ExternalContext externalContext = getContext().getExternalContext();
			OutputStream out = externalContext.getResponseOutputStream();
			externalContext.setResponseContentType("application/rtf");
			
			// Imposta il nome del file generato
			String filename = "Verbale-" + new Timestamp(System.currentTimeMillis()) + ".rtf";
			externalContext.setResponseHeader("Content-Disposition","inline; filename=" + filename);
			
			application.generaVerbale(ids, out);
		} catch (Exception e) {
			addWarnMessage(getSettings().getProperty("msgErroreGenerazioneVerbale"));
		}
	}
	
	/* -----------
	 * Sottoclassi
	 * ----------- */
	
	/**
	 * InsegnamentoBean incapsula un insegnamento fornendo alcune funzionalita' aggiuntive.<br>
	 * Permette di associare all'insegnamento la richiesta del docente che e'
	 * stato assegnato all'insegnamento.
	 * 
	 * @author Lorenzo Porzi
	 *
	 */
	public class InsegnamentoBean {
		private InsegnamentoCorso insegnamento; // L'insegnamento incapsulato
		private RichiestaRegistrazioneDocente assegnazione; // La richiesta scelta
		private RichiestaRegistrazioneDocente[] richieste; // Le richieste per questo insegnamento
		
		/**
		 * Costruisce un InsegnamentoBean associato ad un Insegnamento.<br>
		 * Le richieste per questo insegnamento vengono subito caricate.
		 * 
		 * @param insegnamento l'Insegnamento da associare a questo oggetto.
		 */
		public InsegnamentoBean(InsegnamentoCorso insegnamento) {
			RichiestaNonAssegnata nonAssegnata = new RichiestaNonAssegnata();
			
			this.insegnamento = insegnamento;
			this.assegnazione = nonAssegnata;
			
			// Carica le richieste
			try {
				RichiestaRegistrazioneDocente[] tempRichieste = application.getRichieste(insegnamento.getInsegnamento());
				
				if (tempRichieste.length > 0) {
					richieste = new RichiestaRegistrazioneDocente[tempRichieste.length + 1];
					System.arraycopy(tempRichieste, 0, richieste, 0, tempRichieste.length);
					richieste[tempRichieste.length] = nonAssegnata;
				} else {
					richieste = new RichiestaRegistrazioneDocente[0];
				}
			} catch (ApplicationException e) {
				// Ritorna un array vuoto
				RichiestaRegistrazioneDocente[] vuoto = {};
				richieste = vuoto;
			}
		}
		
		/* ----------------------------------
		 * Setters e getters per le proprietà
		 * ---------------------------------- */

		public InsegnamentoCorso getInsegnamento() {
			return insegnamento;
		}
		
		public RichiestaRegistrazioneDocente getAssegnazione() {
			return assegnazione;
		}
		
		public void setAssegnazione(RichiestaRegistrazioneDocente assegnazione) {
			this.assegnazione = assegnazione;
		}
		
		/* --------------------------------
		 * Metodi per l'estrazione dei dati
		 * -------------------------------- */
		
		public RichiestaRegistrazioneDocente[] getRichieste() {
			return richieste;
		}
		
		public int getNumeroRichieste() {
			return richieste.length;
		}
		
		/**
		 * @return l'implementazione di {@link javax.faces.convert.Converter} necessaria per gestire i pulsanti
		 * di selezione delle richieste.
		 */
		public javax.faces.convert.Converter getAssegnazioneConverter() {
			return new javax.faces.convert.Converter() {		
				@Override
				public Object getAsObject(FacesContext context, UIComponent component,
						String value) {
					RichiestaRegistrazioneDocente richiestaTrovata = null;
				
					// Cerca la richiesta
					for (RichiestaRegistrazioneDocente richiesta : richieste)
						if (richiesta.getNomeUtenteDocente().equals(value))
							richiestaTrovata = richiesta;
				
					return richiestaTrovata;
				}

				@Override
				public String getAsString(FacesContext context, UIComponent component,
						Object value) {
					RichiestaRegistrazioneDocente richiesta = (RichiestaRegistrazioneDocente)value;
				
					return richiesta.getNomeUtenteDocente();
				}		
			};
			
		}
	}
	
	private class RichiestaNonAssegnata extends RichiestaRegistrazioneDocente {
		
		private RichiestaNonAssegnata() {
			super(new Docente(), new Registrazione(), new Richiesta());
		}
		
		public String getNomeUtenteDocente() {
			return "nessuno";
		}
		
		public String toString() {
			return "Nessuno";
		}
	}
}
